# Author: Yubin Lim(purewell@gmail.com)
# Date: 2008-01-18
# License: BSD License
# Copyright: All rights reserved by Yubin Lim.

include(CheckIncludeFile)
include(CheckFunctionExists)
include(CheckTypeSize)
include(CheckStructHasMember)

# Required CMake Version
cmake_minimum_required(VERSION 2.8)
set(CMAKE_USE_RELATIVE_PATHS true)

# Project is libpurewell
project(libpurewell)

# System name
if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" )
	set(LINUX 1)
endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" )

if ( ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" )
	set(FREEBSD 1)
	set(BSD 1)
endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" )

if ( ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" )
	set(OPENBSD 1)
	set(BSD 1)
endif ( ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" )

# Check OS
if (WIN32)
	set(__PW_OS_WIN32 1)
endif(WIN32)

if (UNIX)
	set(__PW_OS_UNIX 1)
endif(UNIX)

if (LINUX)
	set(__PW_OS_LINUX 1)
endif(LINUX)

if (BSD)
	set(__PW_OS_BSD 1)
endif(BSD)

if (FREEBSD)
	set(__PW_OS_FREEBSD 1)
endif(FREEBSD)

if (OPENBSD)
	set(__PW_OS_OPENBSD 1)
endif(OPENBSD)

# Project Version
set(PROJECT_MAJOR_VERSION "0")
set(PROJECT_MINOR_VERSION "2")
set(PROJECT_PATCH_VERSION "0")
set(PROJECT_RELEASE_VERSION "0")
set(PROJECT_VERSION "${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION}-${PROJECT_RELEASE_VERSION}")

set(PW_HDRS "${PROJECT_SOURCE_DIR}/include/purewell")

# Verbose mode
set(CMAKE_VERBOSE_MAKEFILE 0)

# Output path
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin")

set(BUILD_SHARED_LIBS ON)
set(CMAKE_BUILD_TYPE "RelWithDebInfo")

# Library Directory Name
if ( "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" )
	set(LIBDIRNAME "lib64")
else ( "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" )
	set(LIBDIRNAME "lib")
endif ( "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" )

# Install Position
if (UNIX)
	set(CMAKE_INSTALL_PREFIX "/usr/")
endif (UNIX)

# Required libraries
if (LINUX)
	set(CMAKE_REQUIRED_LIBRARIES "-lpthread -lrt -ldl")
endif (LINUX)

if (BSD)
	set(CMAKE_REQUIRED_LIBRARIES "-lpthread")
endif (BSD)

if (WIN32)
	set(CMAKE_REQUIRED_LIBRARIES "ws2_32.lib")
endif (WIN32)

# Check include files...
check_include_file("dirent.h" __PW_HAVE_DIRENT_H)
check_include_file("dlfcn.h" __PW_HAVE_DLFCN_H)
check_include_file("fcntl.h" __PW_HAVE_FCNTL_H)
check_include_file("inttype.h" __PW_HAVE_INTTYPE_H)
check_include_file("ioctl.h" __PW_HAVE_IOCTL_H)
check_include_file("mqueue.h" __PW_HAVE_MQUEUE_H)
check_include_file("poll.h" __PW_HAVE_POLL_H)
check_include_file("semaphore.h" __PW_HAVE_SEMAPHORE_H)
check_include_file("signal.h" __PW_HAVE_SIGNAL_H)
check_include_file("stat.h" __PW_HAVE_STAT_H)
check_include_file("statvfs.h" __PW_HAVE_STATVFS_H)
check_include_file("stddef.h" __PW_HAVE_STDDEF_H)
check_include_file("stdint.h" __PW_HAVE_STDINT_H)
check_include_file("sys/dirent.h" __PW_HAVE_SYS_DIRENT_H)
check_include_file("sys/epoll.h" __PW_HAVE_SYS_EPOLL_H)
check_include_file("sys/ioctl.h" __PW_HAVE_SYS_IOCTL_H)
check_include_file("sys/mman.h" __PW_HAVE_SYS_MMAN_H)
check_include_file("sys/poll.h" __PW_HAVE_SYS_POLL_H)
check_include_file("sys/select.h" __PW_HAVE_SYS_SELECT_H)
check_include_file("sys/signal.h" __PW_HAVE_SYS_SIGNAL_H)
check_include_file("sys/stat.h" __PW_HAVE_SYS_STAT_H)
check_include_file("sys/statvfs.h" __PW_HAVE_SYS_STATVFS_H)
check_include_file("sys/time.h" __PW_HAVE_SYS_TIME_H)
check_include_file("sys/un.h" __PW_HAVE_SYS_UN_H)
check_include_file("time.h" __PW_HAVE_TIME_H)
check_include_file("unistd.h" __PW_HAVE_UNISTD_H)

# Check functions...
check_function_exists("fcntl" __PW_HAVE_FCNTL)
check_function_exists("ioctl" __PW_HAVE_IOCTL)

#set(CMAKE_REQUIRED_LIBRARIES "ws2_32")
#check_function_exists("ioctlsocket" __PW_HAVE_IOCTLSOCKET)
#set(CMAKE_REQUIRED_LIBRARIES)

check_function_exists("gettimeofday" __PW_HAVE_GETTIMEOFDAY)
check_function_exists("GetSystemTimeAsFileTime" __PW_HAVE_GETSYSTEMTIMEASFILETIME)

check_function_exists("strcasecmp" __PW_HAVE_STRCASECMP)
check_function_exists("stricmp" __PW_HAVE_STRICMP)
check_function_exists("vsnprintf" __PW_HAVE_VSNPRINTF)

check_function_exists("epoll_ctl" __PW_HAVE_EPOLL_CTL)
check_function_exists("poll" __PW_HAVE_POLL)

check_function_exists("stat" __PW_HAVE_STAT)
check_function_exists("fstat" __PW_HAVE_FSTAT)
check_function_exists("lstat" __PW_HAVE_LSTAT)
check_function_exists("statvfs" __PW_HAVE_STATVFS)
check_function_exists("fstatvfs" __PW_HAVE_FSTATVFS)

check_function_exists("pthread_barrier_init" __PW_HAVE_POSIX_BARRIER)
check_function_exists("pthread_mutex_init" __PW_HAVE_POSIX_MUTEX)
check_function_exists("pthread_rwlock_init" __PW_HAVE_POSIX_RWLOCK)
check_function_exists("pthread_cond_init" __PW_HAVE_POSIX_CONDITION)
check_function_exists("pthread_spin_init" __PW_HAVE_POSIX_SPIN)
check_function_exists("pthread_spin_timedlock" __PW_HAVE_POSIX_SPIN_TIMEDLOCK)
check_function_exists("pthread_condattr_setclock" __PW_HAVE_PTHREAD_CONDATTR_SETCLOCK)
check_function_exists("pthread_condattr_getclock" __PW_HAVE_PTHREAD_CONDATTR_GETCLOCK)

check_function_exists("opendir" __PW_HAVE_OPENDIR)

# Check types...
check_type_size("void* restrict" __PW_HAVE_RESTRICT)
check_type_size("void* __restrict__" __PW_HAVE_RESTRICT_CPP)
check_type_size("size_t" __PW_HAVE_SIZE_T)
check_type_size("ssize_t" __PW_HAVE_SSIZE_T)
check_type_size("intptr_t" __PW_HAVE_INTPTR_T)
check_type_size("uint8_t" __PW_HAVE_UINT8_T)
check_type_size("long long" __PW_HAVE_LONG_LONG_T)
check_type_size("__int64" __PW_HAVE___INT64_T)
check_type_size("void*" __PW_HAVE_POINTER_T)

if (WIN32)
	set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
else (WIN32)
	set(CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h")
endif (WIN32)
check_type_size("struct sockaddr_storage" __PW_HAVE_SOCKADDR_STORAGE_T)
check_type_size("socklen_t" __PW_HAVE_SOCKLEN_T)
set(CMAKE_EXTRA_INCLUDE_FILES)

set(CMAKE_EXTRA_INCLUDE_FILES "sys/un.h")
check_type_size("struct sockaddr_un" __PW_HAVE_SOCKADDR_UN_T)
set(CMAKE_EXTRA_INCLUDE_FILES)

if (__PW_HAVE_SYS_TIME_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "sys/time.h")
else (__PW_HAVE_SYS_TIME_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "time.h")
endif (__PW_HAVE_SYS_TIME_H)
check_type_size("clockid_t" __PW_HAVE_CLOCKID_T)
set(CMAKE_EXTRA_INCLUDE_FILES)

if (WIN32)
	set(CMAKE_EXTRA_INCLUDE_FILES "winsock2.h")
else (WIN32)
	if (__PW_HAVE_SYS_TIME_H)
		set(CMAKE_EXTRA_INCLUDE_FILES "sys/time.h")
	else (__PW_HAVE_SYS_TIME_H)
		set(CMAKE_EXTRA_INCLUDE_FILES "time.h")
	endif (__PW_HAVE_SYS_TIME_H)
endif (WIN32)
check_type_size("struct timeval" __PW_HAVE_TIMEVAL_T)
set(CMAKE_EXTRA_INCLUDE_FILES)

if (__PW_HAVE_STAT_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "stat.h")
endif (__PW_HAVE_STAT_H)
if (__PW_HAVE_SYS_STAT_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "sys/stat.h")
endif (__PW_HAVE_SYS_STAT_H)
check_type_size("struct stat" __PW_HAVE_STAT_T)
check_type_size("dev_t" __PW_HAVE_DEV_T)
check_type_size("ino_t" __PW_HAVE_INO_T)
check_type_size("mode_t" __PW_HAVE_MODE_T)
check_type_size("nlink_t" __PW_HAVE_NLINK_T)
check_type_size("uid_t" __PW_HAVE_UID_T)
check_type_size("gid_t" __PW_HAVE_GID_T)
check_type_size("off_t" __PW_HAVE_OFF_T)
check_type_size("blksize_t" __PW_HAVE_BLKSIZE_T)
check_type_size("__blksize_t" __PW_HAVE___BLKSIZE_T)
check_type_size("blkcnt_t" __PW_HAVE_BLKCNT_T)
check_type_size("fsblkcnt_t" __PW_HAVE_FSBLKCNT_T)
check_struct_has_member("struct stat" st_blksize "${CMAKE_EXTRA_INCLUDE_FILES}" __PW_HAVE_MEM_STAT_ST_BLKSIZE)
check_struct_has_member("struct stat" st_blocks "${CMAKE_EXTRA_INCLUDE_FILES}" __PW_HAVE_MEM_STAT_ST_BLOCKS)
set(CMAKE_EXTRA_INCLUDE_FILES)

if (__PW_HAVE_STATVFS_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "statvfs.h")
endif (__PW_HAVE_STATVFS_H)
if (__PW_HAVE_SYS_STATVFS_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "sys/statvfs.h")
endif (__PW_HAVE_SYS_STATVFS_H)
check_type_size("struct statvfs" __PW_HAVE_STATVFS_T)
set(CMAKE_EXTRA_INCLUDE_FILES)

if (__PW_HAVE_SIGNAL_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "signal.h")
endif (__PW_HAVE_SIGNAL_H)
if (__PW_HAVE_SYS_SIGNAL_H)
	set(CMAKE_EXTRA_INCLUDE_FILES "sys/signal.h")
endif (__PW_HAVE_SYS_SIGNAL_H)
check_type_size("sigset_t" __PW_HAVE_SIGSET_T)
check_type_size("siginfo_t" __PW_HAVE_SIGINFO_T)
set(CMAKE_EXTRA_INCLUDE_FILES)

configure_file("${PW_HDRS}/purewell.hpp.in" "${PW_HDRS}/purewell.hpp")
configure_file("${PW_HDRS}/types.hpp.in" "${PW_HDRS}/types.hpp")

# Sub-directories
add_subdirectory(doc)
add_subdirectory(include)
add_subdirectory(libsrc)
#add_subdirectory(lib)
#add_subdirectory(src)
#add_subdirectory(test)
add_subdirectory(pack)

